{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": true,
    "pycharm": {
     "name": "#%% md\n"
    }
   },
   "source": [
    "## 梯度下降求解逻辑回归\n",
    "\n",
    "数据说明：\n",
    "  建立一个逻辑回归模型来预测一个学生是否被大学录取\n",
    "  根据2次考试的结果来决定每个申请人的录取机会。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "pycharm": {
     "name": "#%%\n"
    }
   },
   "outputs": [],
   "source": [
    "# 引入数据和模块\n",
    "import os\n",
    "import time\n",
    "import numpy as np\n",
    "import pandas as pd\n",
    "import matplotlib.pyplot as plt\n",
    "%matplotlib inline"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "pycharm": {
     "name": "#%%\n"
    }
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>Exam1</th>\n",
       "      <th>Exam2</th>\n",
       "      <th>Admitted</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>34.623660</td>\n",
       "      <td>78.024693</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>30.286711</td>\n",
       "      <td>43.894998</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>35.847409</td>\n",
       "      <td>72.902198</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>60.182599</td>\n",
       "      <td>86.308552</td>\n",
       "      <td>1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>79.032736</td>\n",
       "      <td>75.344376</td>\n",
       "      <td>1</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "       Exam1      Exam2  Admitted\n",
       "0  34.623660  78.024693         0\n",
       "1  30.286711  43.894998         0\n",
       "2  35.847409  72.902198         0\n",
       "3  60.182599  86.308552         1\n",
       "4  79.032736  75.344376         1"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 载入数据（训练集）\n",
    "path = 'data' + os.sep + 'LogiReg_data.txt'\n",
    "pdData = pd.read_csv(path, header=None, names=['Exam1', 'Exam2', 'Admitted'])\n",
    "\n",
    "pdData.head()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "pycharm": {
     "name": "#%%\n"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Text(0, 0.5, 'Exam2 Score')"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAfQAAAFzCAYAAADIY/vqAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjMuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8vihELAAAACXBIWXMAAAsTAAALEwEAmpwYAAA2PElEQVR4nO3deZhcdb3n8fc3UBJWCRAYJGkTFWVLOpCQmIsgggtcIssIGME2F9Fk5pHYRC8ttIzgPEnuNeBkAle9YYySiTFeQBC8V7ZB9KJoh0bCIgEhklSHByWyJhAgpL/zx++cdHWn91rOUp/X89RTdU5tv1PVXd/zW7/m7oiIiEi2jUi6ACIiIlI+BXQREZEcUEAXERHJAQV0ERGRHFBAFxERyQEFdBERkRzYNekClOOAAw7wcePGJV0MERGRmnjwwQf/5u6je7sv0wF93LhxtLe3J10MERGRmjCzDX3dpyZ3ERGRHFBAFxERyQEFdBERkRzIdB+6iIiUb9u2bWzcuJE33ngj6aJIZOTIkYwZM4ZCoTDo51QtoJvZD4AZwPPuflS0bz/g34BxwHrgXHd/ycwMWAL8PfA68A/u/odqlU1ERLps3LiRvffem3HjxhF+jiVJ7s4LL7zAxo0bGT9+/KCfV80m9+uBU3rsuxS4x90PBe6JtgFOBQ6NLrOB71WxXCIiUuKNN95g//33VzBPCTNj//33H3KLSdUCurv/J/Bij91nAMuj28uBM0v2/18Pfg/sa2YHV6tsIiLSnYJ5ugzn+6j1oLiD3P256PZfgIOi24cAHSWP2xjtExGROvGzn/0MM+OJJ57o9f4TTzxxSGuPtLe38+UvfxmAX/3qV9x///3d3uvxxx8fchn32muvIT+nVhIb5e7uDvhQn2dms82s3czaN23aVIWSiYhIElatWsWHPvQhVq1aVZHXmzJlCtdccw1QuYCeZrUO6H+Nm9Kj6+ej/c8CY0seNybatxN3v87dp7j7lNGje139Lj2KRViwADw6b3EP28VisuUSESlDRwfMnQtTp4brjo6BnzOQLVu28Jvf/IZly5bxk5/8BICtW7cyc+ZMDj/8cM466yy2bt264/F77bUXl1xyCUceeSQf/ehHWb16NSeeeCLvec97uO2224AQxGfMmMH69ev513/9VxYvXsykSZP49a9/zW233cYll1zCpEmTWLduHevWreOUU05h8uTJHH/88TtaCZ555hmmT5/OhAkTuPzyy8s/0Gpy96pdCKPZHyvZvgq4NLp9KbAoun0acDtgwAeB1YN5/cmTJ3uqzZ/vDu7Nze6dneEawn4RkZR4/PHHB/3YYtF91Cj3QiH8nBUKYbtYLK8MP/rRj/zzn/+8u7tPnz7d29vb/dvf/rZfcMEF7u7+8MMP+y677OIPPPCAu4cW3l/84hfu7n7mmWf6xz72MX/rrbd8zZo13tjY6O7u9957r5922mnu7n7FFVf4VVddteP9Zs2a5TfeeOOO7ZNOOsn/9Kc/ubv773//e//IRz7i7u6f/OQnffny5e7u/i//8i++5557lnegQ9Db9wK0ex8xsZrT1lYBJwIHmNlG4Argn4EbzOxCYANwbvTwXxCmrD1NmLZ2QbXKVVOtrbBpEyxZEi4Azc1hv4hIBi1aBFu2wLZtYXvbtrC9aBFce+3wX3fVqlU0NzcDMHPmTFatWsXTTz+9ow984sSJTJw4ccfj3/GOd3DKKWEi1YQJE9htt90oFApMmDCB9evXD+m9t2zZwv33388555yzY9+bb74JwG9/+1t++tOfAtDU1MTXvva1YR9jtVUtoLv7Z/q46+ReHuvAl6pVlsSYweLFXcEcwrZGk4pIRrW1dQXz2LZtsHr18F/zxRdf5Je//CWPPvooZsb27dsxM44++ug+n1MoFHaMBB8xYgS77bbbjttvv/32kN6/s7OTfffdlzVr1vR6f1ZmAGjp12pyh3nzuu+bN6+rT11EJGOmTYOei5cVCqE/fbhuuukmmpqa2LBhA+vXr6ejo4Px48czefJkfvzjHwPw2GOP8cgjjwz7Pfbee282b97c6/Y+++zD+PHjufHGG4HQFf3www8DcNxxx+3o01+5cuWw378WFNCraeHCUDtvbobOznC9ZEnYLyJ9qsagK6mMlhbYa6+uoF4ohO2WluG/5qpVqzjrrLO67fvUpz7FM888w5YtWzj88MP5xje+weTJk4f9Hp/85Ce55ZZbmDRpEvfddx8zZ87kqquu4uijj2bdunWsXLmSZcuW0djYyJFHHsmtt94KwJIlS/jOd77DhAkTePbZXsdqp4Z5hmuLU6ZM8VTnQy8WYcWK0GduFmrmCxdCUxM0NCRatI6O0OfV1hbOuFtaYOzYgZ8nUm0dHdDY2NVPGweMhx/W32i1rF27lsMPP3zQj49/P1avDidd+v2ojt6+FzN70N2n9PZ4BfQ6pB9MSbO5c2Hp0u79tIUCzJlT3qAr6dtQA7rUxlADuprc61B/o1RFklaNQVci9UABvQ7pB1PSrBqDrkTqgQJ6HdIPZv3KwmCzagy6SossfP6SXepDr0PqQ8+/3gY9Qna+9zwOukrz/5360NNpqH3oVVtYRtJr7NjwI5K3H0wJegaONWtg5Uo4/fTqrPBVDWPHll+mtM3kqNYKayIxNbnXqfgHs60tXCuY50dfgeP22+tn7ER8UrN0KTzwQLhubEy2iVtjV/pnZnz1q1/dsX311Vdz5ZVX9vucwWRMmzRpEjNnzuzz/jiBy1B84Qtf2PG+C0vWFXn55Zf57ne/O6TXArjyyiu5+uqrh/y8nhTQRXKmr8AB9TN2Io0zOTR2pX+77bYbN998M3/7298G/ZyBAvratWvZvn079913H6+99lolignA97//fY444gigMgG9UhTQy6H0qJJCfQWOU0/N72CzntJYG87NYL8q/e7tuuuuzJ49m8WLF+903/r16znppJOYOHEiJ598MsVikfvvv3+nFKg9rVq1iqamJj7+8Y/vWPkN4I477uCwww7jmGOO4eabb96x/8orr2TWrFkcf/zxvPvd7+bmm2+mpaWFCRMmcMopp7At+qM68cQTaW9v59JLL2Xr1q1MmjSJ888/n0svvZR169YxadIkLrnkEgCuuuoqjj32WCZOnMgVV1yx470WLFjA+9//fj70oQ/x5JNPlvXZ7dBXGrYsXBJPn6r0qJJC/aW3LBbdL7rIferUcF1uysu0uuiiruOPL4VC2J+ktH7+Q0mfWq3fvT333NNfeeUVf/e73+0vv/yyX3XVVX7FFVe4u/uMGTP8+uuvd3f3ZcuW+RlnnOHuO6dA7en973+/b9iwwe+8806fMWOGu7tv3brVx4wZ43/605+8s7PTzznnnG4pVo877rgdaVh33333bilab7nlFnd3//CHP7wjjWtpOtVnnnnGjzzyyB3bd955p3/xi1/0zs5O3759u5922mn+61//2tvb2/2oo47y1157zV955RV/73vf2y21ayw16VPrgtKjSgoNNOixHgZgtbSEgYA9R5QnXRuuxGC/xFXxd2+fffbhc5/7HNdccw277777jv2/+93vdtSkm5qaaBnEF9ne3s4BBxxAQ0MD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\n",
      "text/plain": [
       "<Figure size 576x432 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "positive = pdData[pdData.Admitted == 1] # 正例\n",
    "negative = pdData[pdData.Admitted == 0] # 负例\n",
    "\n",
    "# 通过散点图 画出 正例 和 负例\n",
    "fig,ax = plt.subplots(figsize=(8,6))\n",
    "ax.scatter(positive['Exam1'], positive['Exam2'], s=30, c='b', marker='o', label='Admitted')\n",
    "ax.scatter(negative['Exam1'], negative['Exam2'], s=30, c='r', marker='x', label='Not Admitted')\n",
    "ax.legend()\n",
    "ax.set_xlabel('Exam1 Score')\n",
    "ax.set_ylabel('Exam2 Score')\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 如何实现 逻辑回归\n",
    "目标：简历分类器，求解三个参数\n",
    "设定阈值，根据阈值判断录取结果\n",
    "\n",
    "#### 要完成的模块\n",
    " * sigmoid： 映射到概率的函数\n",
    " * model： 返回预测结果的值\n",
    " * cost ： 根据参数计算损失\n",
    " * gradient 计算每个参数的梯度\n",
    " * descent 进行参数更新\n",
    " * accuracy  计算精度"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "sigmoid 函数:\n",
    "\n",
    "$ g(z) = \\frac { 1 } { 1 + e^z } $\n",
    "\n",
    "sigmoid 函数的取值: g(0) = 0.5 , g(-)=0, g(+)=1"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "pycharm": {
     "name": "#%%\n"
    }
   },
   "outputs": [],
   "source": [
    "def sigmoid(z):\n",
    "    return 1 / (1 + np.exp(-z))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "pycharm": {
     "name": "#%%\n"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[<matplotlib.lines.Line2D at 0x7fd8c6ec4d00>]"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 576x432 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "# 绘制 sigmoid 函数的取曲线\n",
    "nums = np.arange(-10,10, 1)\n",
    "fig,ax = plt.subplots(figsize=(8,6))\n",
    "ax.plot(nums, sigmoid(nums),'r')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {
    "pycharm": {
     "name": "#%%\n"
    }
   },
   "outputs": [],
   "source": [
    "# 预测函数  得到预测结果  矩阵相乘\n",
    "def model(X, theta):\n",
    "    return sigmoid(np.dot(X, theta.T))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {
    "pycharm": {
     "name": "#%%\n"
    }
   },
   "outputs": [],
   "source": [
    "# 插入一列\n",
    "#pdData.insert(0, 'Ones', 1)\n",
    "orig_data = pdData.values\n",
    "\n",
    "X = orig_data[:,0:-1]\n",
    "Y = orig_data[:,-1:]\n",
    "theta = np.zeros([1,3])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "损失 函数:\n",
    "\n",
    "* 将对数似然函数去负号\n",
    "\n",
    "  $ D(h_θ(x),y) = -ylog(h_θ (x))-(1-y)log(1-h_θ(x)) $\n",
    "\n",
    "* 求平均损失\n",
    "\n",
    "  $ J(θ) = \\frac { 1 } { n } \\sum_{i=1}^n D(h_θ(x_i),y_i) $"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {
    "pycharm": {
     "name": "#%%\n"
    }
   },
   "outputs": [],
   "source": [
    "# 定义损失函数 （对数似然函数 ）\n",
    "def cost(X, y, theta):\n",
    "    # 计算损失函数 按照公式\n",
    "    left = np.multiply(-y, np.log(model(X, theta)))  # 左边的连乘\n",
    "    right = np.multiply((1 - y), np.log(1 - model(X, theta))) # 右边的连乘\n",
    "    return np.sum(left - right) / (len(X))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {
    "pycharm": {
     "name": "#%%\n"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0.6931471805599453"
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "cost(X, Y, theta)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "计算梯度\n",
    "\n",
    "  $ \\frac { \\partial J } { \\partial θ_i } = -\\frac { 1 } { m }\\sum_{i=1}^n (y_i-h_θ(x_i))x_{ij} $"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {
    "pycharm": {
     "name": "#%%\n"
    }
   },
   "outputs": [],
   "source": [
    "def gradient(X, y, theta):\n",
    "    # 求解梯度 grad为 theta梯度的更新值\n",
    "    grad = np.zeros(theta.shape)\n",
    "    error = (model(X, theta) - y).ravel()\n",
    "    for j in range(len(theta.ravel())):\n",
    "\n",
    "        temp = np.multiply(error, X[:,j])\n",
    "        grad[0, j] = np.sum(temp) / len(X)\n",
    "\n",
    "    return grad\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "求解梯度\n",
    "\n",
    "比较3种不同梯度下降的方法"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {
    "pycharm": {
     "name": "#%%\n"
    }
   },
   "outputs": [],
   "source": [
    "# 设定三种停止策略 分别是按迭代次数、按损失函数的变化量、按梯度的变化量\n",
    "STOP_ITER = 0\n",
    "STOP_COST = 1\n",
    "STOP_GRAD = 2\n",
    "\n",
    "# threshold为指定阈值\n",
    "def stopCriterion(stype, value, threshold):\n",
    "    # 设定三种不同的停止策略\n",
    "    if stype == STOP_ITER:\n",
    "        return value > threshold # 按迭代次数停止\n",
    "\n",
    "    elif stype == STOP_COST:\n",
    "        return abs(value[-1]-value[-2]) < threshold  # 按损失函数是否改变停止\n",
    "\n",
    "    elif stype == STOP_GRAD:\n",
    "        return np.linalg.norm(value) < threshold # 按梯度大小停止"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {
    "pycharm": {
     "name": "#%%\n"
    }
   },
   "outputs": [],
   "source": [
    "def shuffleData(data):\n",
    "    # 洗牌 防止数据有一定的排列规律\n",
    "    np.random.shuffle(data) # 乱序\n",
    "    cols = data.shape[1]\n",
    "    X = data[:, 0:cols-1]\n",
    "    y = data[:, cols-1:]\n",
    "    return X, y"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {
    "pycharm": {
     "name": "#%%\n"
    }
   },
   "outputs": [],
   "source": [
    "def descent(data, theta, batchSize, stopType, thresh, alpha):\n",
    "    # 最主要的函数 梯度下降求解\n",
    "    # batchSize：为1代表随机梯度下降  为整体值表示批量梯度下降  为某一数值时表示小批量梯度下降\n",
    "    # stopType 停止策略类型\n",
    "    # thresh 阈值\n",
    "    # alpha 学习率\n",
    "\n",
    "    init_time = time.time()\n",
    "    i = 0 # 迭代次数\n",
    "    k = 0 # batch 迭代数据的初始量\n",
    "    X, y = shuffleData(data)\n",
    "    grad = np.zeros(theta.shape) # 计算的梯度\n",
    "    costs = [cost(X, y, theta)] # 损失值\n",
    "\n",
    "    while True:\n",
    "        # batchSize为指定的梯度下降策略\n",
    "        grad = gradient(X[k:k+batchSize], y[k:k+batchSize], theta)\n",
    "        k += batchSize #取batch数量个数据\n",
    "        if k >= n:\n",
    "            k = 0\n",
    "            X, y = shuffleData(data) # 重新洗牌\n",
    "        theta = theta - alpha*grad # 参数更新\n",
    "        costs.append(cost(X, y, theta)) # 计算新的损失\n",
    "        i += 1\n",
    "\n",
    "        if stopType == STOP_ITER:\n",
    "            value = i\n",
    "        elif stopType == STOP_COST:\n",
    "            value = costs\n",
    "        elif stopType == STOP_GRAD:\n",
    "            value = grad\n",
    "\n",
    "        if stopCriterion(stopType, value, thresh):\n",
    "            break\n",
    "\n",
    "    return theta, i-1, costs, grad, time.time() - init_time"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {
    "pycharm": {
     "name": "#%%\n"
    }
   },
   "outputs": [],
   "source": [
    "def runExpe(data, theta, batchSize, stopType, thresh, alpha):\n",
    "    # 损失率与迭代次数的展示函数\n",
    "    theta, iter, costs, grad, dur = descent(data, theta, batchSize, stopType, thresh, alpha)\n",
    "    name = \"Original\" if (data[:,1]>2).sum() > 1 else \"Scaled\"\n",
    "    name += \" data - learning rate: {} - \".format(alpha)\n",
    "\n",
    "    if batchSize == n:\n",
    "        strDescType = \"Gradient\"\n",
    "\n",
    "    elif batchSize == 1:\n",
    "        strDescType = \"Stochastic\"\n",
    "\n",
    "    else:\n",
    "        strDescType = \"Mini-batch ({})\".format(batchSize)\n",
    "\n",
    "    name += strDescType + \" descent - Stop: \"\n",
    "\n",
    "    if stopType == STOP_ITER:\n",
    "        strStop = \"{} iterations\".format(thresh)\n",
    "\n",
    "    elif stopType == STOP_COST:\n",
    "        strStop = \"costs change < {}\".format(thresh)\n",
    "\n",
    "    else:\n",
    "        strStop = \"gradient norm < {}\".format(thresh)\n",
    "\n",
    "    name += strStop\n",
    "    print(\"***{}\\nTheta: {} - Iter: {} - Last cost: {:03.2f} - Duration: {:03.2f}s\".format(\n",
    "        name, theta, iter, costs[-1], dur))\n",
    "    fig, ax = plt.subplots(figsize=(12,4))\n",
    "    ax.plot(np.arange(len(costs)), costs, 'r')\n",
    "    ax.set_xlabel('Iterations')\n",
    "    ax.set_ylabel('Cost')\n",
    "    ax.set_title(name.upper() + ' - Error vs. Iteration')\n",
    "\n",
    "    return theta"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "pycharm": {
     "name": "#%% md\n"
    }
   },
   "source": [
    "### 不同的停止策略\n",
    "\n",
    "#### 设定迭代次数"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {
    "pycharm": {
     "name": "#%%\n"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "***Original data - learning rate: 1e-07 - Gradient descent - Stop: 5000 iterations\n",
      "Theta: [[1.62799405e-05 3.69532228e-03 3.31925740e-03]] - Iter: 5000 - Last cost: 0.64 - Duration: 1.62s\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "array([[1.62799405e-05, 3.69532228e-03, 3.31925740e-03]])"
      ]
     },
     "execution_count": 20,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 864x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "# 选择梯度下降方法是基于所有样本的\n",
    "n = 100 # 数据量也是100 相当于对整个样本进行计算\n",
    "runExpe(orig_data, theta, n, STOP_ITER, thresh=5000, alpha=0.0000001)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "pycharm": {
     "name": "#%%\n"
    }
   },
   "outputs": [],
   "source": [
    " # in a try / except structure so as not to return an error if the block si executed several times\n",
    "orig_data = pdData.as_matrix()\n",
    "cols = orig_data.shape[1]\n",
    "X = orig_data[:,0:cols-1]\n",
    "y = orig_data[:,cols-1:cols]\n",
    "\n",
    "theta = np.zeros([1, 3])"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.2"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 1
}